package xxx

import (
	"iter"
)

type node[T any] struct {
	next  *node[T]
	value T
}

type LinkedList[T any] struct {
	head *node[T]
}

func (l *LinkedList[T]) PushFront(v T) {
	newNode := &node[T]{
		value: v,
		next:  nil,
	}
	if l.head == nil {
		l.head = newNode
		return
	} else {
		newNode.next = l.head
		l.head = newNode
	}
}

func (l *LinkedList[T]) PushBack(v T) {
	newNode := &node[T]{
		value: v,
		next:  nil,
	}
	if l.head == nil {
		l.head = newNode
	} else {
		node := l.head
		for node.next != nil {
			node = node.next
		}
		node.next = newNode
	}
}

func (l *LinkedList[T]) PopFront() *T {
	if l.head.next != nil {
		res := l.head.value
		l.head = l.head.next
		return &res
	}
	return nil
}

func (l *LinkedList[T]) PopBack() *T {
	if l.head == nil {
		return nil
	}
	if l.head.next == nil {
		res := l.head.value
		l.head = nil
		return &res
	}
	node := l.head
	for node.next.next != nil {
		node = node.next
	}
	res := node.next.value
	node.next = nil
	return &res
}

func (l *LinkedList[T]) Iter() iter.Seq[T] {
	return func(yield func(T) bool) {
		current := l.head
		for current != nil {
			if !yield(current.value) {
				return
			}
			current = current.next
		}
	}
}
